/**
 * @Author       : Hejh(3010733382@qq.com)
 * @Version      : V1.0
 * @Date         : 2024-01-14 17:39:31
 * @Description  : 试卷接口控制器
 */
const fs = require('fs')
const XLSX = require('xlsx')
const path = require('path')
const Mysequelize = require('@/models')
const R = require('@/models/Response')
const {
  Paper,
  Question,
  Chapter,
  Exam,
  ExamHistory,
  ErrorQuestion,
  QuestionFav
} = require('@/models/model')
const { ERROR_USER_CODE } = require('@/constants/errorCode')
const { generatId } = require('@/utils/idUtil')
const { delModel, sortModel } = require('@/utils/controllerCommon')
const { Document, Packer, Paragraph, TextRun } = require('docx')
const { model } = require('mongoose')
const { Op } = require('sequelize')

/**
 * 列表查询试卷接口
 * @param {*} ctx
 * @returns
 */
module.exports.listPaper = async (ctx) => {
  const orderCondition = [['sort']]
  const { page, pageSize, chapterId } = ctx.query
  const start = (page - 1) * pageSize
  const whereCondition = {}
  if (chapterId !== undefined) {
    whereCondition.chapterId = chapterId
  }
  const { rows, count } = await Paper.findAndCountAll({
    where: whereCondition,
    offset: +start,
    include: [
      {
        model: Chapter
      },
      {
        model: Exam
      },
      {
        model: ExamHistory
      }
    ],
    limit: +pageSize,
    order: orderCondition,
    distinct: true
  })

  // 查询paper的时候带上题目数量
  for (let i = 0; i < rows.length; i++) {
    const cnt = await Question.count({
      where: {
        paperId: rows[i].id
      }
    })
    rows[i].dataValues.questionCnt = cnt
  }

  ctx.body = R.success({
    page,
    pageSize,
    total: count,
    pages: Math.ceil(count / pageSize),
    items: rows
  })
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 创建试卷接口
 * @param {*} ctx
 */
module.exports.createPaper = async (ctx) => {
  const { name, pic, chapterId, people, time, url } = ctx.request.body
  const t = await Mysequelize.transaction()
  const nextId = generatId()
  const sort = await Paper.max('sort')

  let createObj = {
    id: nextId,
    name,
    chapterId,
    sort: sort + 1,
    createUser: ctx.user.id,
    updateUser: ctx.user.id
  }
  if (pic !== undefined) {
    createObj.pic = pic
  }
  if (people !== undefined) {
    createObj.people = people
  }
  if (time !== undefined) {
    createObj.time = time
  }

  // 根据chapterId获取examId
  const chapter = await Chapter.findByPk(BigInt(chapterId))
  createObj.examId = chapter.examId
  try {
    // 到这里可以进行试卷的添加了,排序字段默认是最大值
    const paper = await Paper.create(createObj, {
      transaction: t
    })

    // 处理url存在的情况
    if (url) {
      const path2 = path.join(__dirname, '../public/', url)
      // 解析试卷excel，添加试题
      const workbook = XLSX.readFile(path2)
      const sheetName = workbook.SheetNames[0]
      const sheet = workbook.Sheets[sheetName]
      const data = XLSX.utils.sheet_to_json(sheet)
      // console.log(data)
      const maxQ = await Question.max('sort')
      const questions = data.map((item, index) => {
        const aId = generatId()
        return {
          id: aId,
          ...item,
          paperId: paper.id,
          sort: maxQ + index + 1,
          pic: item.pic ? item.pic : '',
          anaPics: item.anaPics ? item.anaPics : '',
          score: item.score ? item.score : 1,
          type: item.type ? item.type : 1,
          createUser: ctx.user.id,
          updateUser: ctx.user.id
        }
      })

      // 创建题目
      await Question.bulkCreate(questions, {
        transaction: t
      })
    }
    await t.commit()
    ctx.body = R.success()
  } catch (error) {
    console.log(error, 'paper')
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.PAPER_CREATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 更新试卷接口
 * @param {*} ctx
 */
module.exports.updatePaper = async (ctx) => {
  const t = await Mysequelize.transaction()
  const { paperId, name, chapterId, people, time, pic } = ctx.request.body
  const updateObj = {
    name
  }
  if (chapterId) {
    updateObj.chapterId = chapterId
    // 同时更新examId
    const chapter = await Chapter.findByPk(BigInt(chapterId))
    updateObj.examId = chapter.examId
  }
  if (people) {
    updateObj.people = people
  }
  if (time) {
    updateObj.time = time
  }

  if (pic) {
    updateObj.pic = pic
  }

  try {
    // 进行试卷信息的更新
    await Paper.update(updateObj, {
      where: {
        id: BigInt(paperId)
      },
      transaction: t
    })
    await t.commit()
    ctx.body = R.success()
  } catch (e) {
    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.PAPER_UPDATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 试卷变更章节接口
 * @param {*} ctx
 */
module.exports.changeChapterPaper = async (ctx) => {
  const t = await Mysequelize.transaction()
  const { paperIds, chapterId } = ctx.request.body
  const updateObj = {}
  if (chapterId) {
    updateObj.chapterId = chapterId
    // 同时更新examId
    const chapter = await Chapter.findByPk(BigInt(chapterId))
    updateObj.examId = chapter.examId
  }
  try {
    // 进行试卷信息的更新
    await Paper.update(updateObj, {
      where: {
        id: {
          [Op.in]: paperIds
        }
      },
      transaction: t
    })
    await t.commit()
    ctx.body = R.success()
  } catch (e) {
    console.log(e, 'eerrrrr')

    await t.rollback()
    ctx.body = R.error(ERROR_USER_CODE.PAPER_UPDATE_ERROR)
  }
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 批量删除试卷接口
 * @param {*} ctx
 */
module.exports.delPapers = async (ctx) => {
  await delModel(
    Paper,
    ERROR_USER_CODE.PAPER_DEL_ERROR,
    'paperIds'
  )(ctx, [
    { model: Question, idName: 'paperId' },
    { model: ExamHistory, idName: 'paperId' },
    { model: ErrorQuestion, idName: 'paperId' },
    { model: QuestionFav, idName: 'paperId' }
  ])
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 试卷排序接口
 * @param {*} ctx
 */
module.exports.sortPapers = async (ctx) => {
  // 传递的试卷ID顺序即为排序顺序，取出这些ID对应的sort，sort从小到大排序后，依次赋值
  await sortModel(Paper, ERROR_USER_CODE.PAPER_SORT_ERROR, 'paperIds')(ctx)
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 试卷上传
 * @param {*} ctx
 */
module.exports.uploadPaper = async (ctx, info, userId, t) => {
  const nextId = generatId()
  const aPaper = await Paper.findByPk(BigInt(info.parentId))
  if (!aPaper) {
    throw new Error('父级试卷不存在')
  }
  const sort = await Paper.max('sort')
  await Paper.create(
    {
      id: nextId,
      name: info.filename,
      chapterId: info.parentId,
      examId: aPaper.examId,
      sort,
      createUser: userId,
      updateUser: userId
    },
    {
      transaction: t
    }
  )
  const url = path.join(
    __dirname,
    '../public/upload/file/',
    info.fileId,
    info.filename
  )
  // 解析试卷excel，添加试题
  const workbook = XLSX.readFile(url)
  const sheetName = workbook.SheetNames[0]
  const sheet = workbook.Sheets[sheetName]
  const data = XLSX.utils.sheet_to_json(sheet)

  console.log(data, 'xxx')
}

/**
 * @author: Hejh(3010733382@qq.com)
 * @description: 试卷导出word接口
 * @param {*} ctx
 */

module.exports.exportPaper = async (ctx) => {
  const { paperId, hasAnswer = false } = ctx.request.body
  const paper = await Paper.findByPk(BigInt(paperId))

  const questions = await Question.findAll({
    where: {
      paperId: BigInt(paperId)
    },
    order: [['sort', 'ASC']]
  })

  let mySelect = [{ properties: {}, children: [] }]
  questions.forEach((question, index) => {
    mySelect[0].children.push(
      ...[
        // new Paragraph({
        //   children: [
        //     new TextRun({
        //       text: `${index + 1}. ${question.name
        //         .replace(/<font\b[^>]*>(.*?)<\/font>/gi, '')
        //         .replace(/<br\s*\/?>/gi, '\n')
        //         .replace(/\s+/g, '')}`
        //       // bold: true
        //     })
        //   ]
        // }),

        ...question.name
          .replace(/<font\b[^>]*>(.*?)<\/font>/gi, '')
          .replace(/\s+/g, '')
          .split('<br>')
          .map((v, index2) => {
            return new Paragraph({
              children: [
                new TextRun({
                  text: index2 === 0 ? `第${index + 1}题:${v}` : v
                })
              ]
            })
          }),

        ...(question.options
          ? question.options.split('||').map(
              (option, optIndex) =>
                new Paragraph({
                  indent: { left: 420 }, // 420 twips 对应 2 个字符的缩进
                  children: [
                    new TextRun({
                      text: `${String.fromCharCode(65 + optIndex)}. ${option.trim()}`
                    })
                  ]
                })
            )
          : []),
        hasAnswer
          ? new Paragraph({
              children: [
                new TextRun({
                  text: `答案: ${question.answer}`,
                  color: 'FF0000'
                })
              ]
            })
          : new Paragraph({}),
        ...(hasAnswer
          ? question.analysis
              .replace(/<span\b[^>]*>(.*?)<\/span>/gi, '')
              .split('<br>')
              .map((v, index3) => {
                return new Paragraph({
                  children: [
                    new TextRun({
                      text: index3 === 0 ? '解析:' + v : v,
                      color: 'FF0000'
                    })
                  ]
                })
              })
          : [new Paragraph({})]),
        new Paragraph({}),
        new Paragraph({}) // 添加一个空段落以分隔题目
      ]
    )
  })

  const doc = new Document({
    creator: 'hejh',
    title: hasAnswer ? paper.name + '带答案' : paper.name,
    sections: mySelect
  })

  const buffer = await Packer.toBuffer(doc)

  const finaName = hasAnswer
    ? paper.name + paperId + '带答案' + '.docx'
    : paper.name + paperId + '.docx'

  const url = path.join(__dirname, '../public/upload/file/', finaName)

  fs.writeFileSync(url, buffer)

  ctx.body = R.success({
    url: '/upload/file/' + finaName
  })
}

module.exports.getPaperById = async (ctx) => {
  const { paperId } = ctx.query
  const paper = await Paper.findOne({
    where: {
      id: paperId
    },
    include: [
      {
        model: Exam
      },
      {
        model: Chapter
      },
      {
        model: Question
      }
    ]
  })

  ctx.body = R.success({
    paper
  })
}
